package com.syh.jn.scm.infrastructure.repository.impl.downstream.logistics;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.wrapper.Wrapper;
import com.syh.core.ddd.infrastructure.repository.AbstractAggregateRepository;
import com.syh.jn.scm.domain.downstream.entity.logistics.DownLogisticsBill;
import com.syh.jn.scm.domain.downstream.entity.logistics.DownLogisticsBillItem;
import com.syh.jn.scm.domain.downstream.repository.logistics.DownLogisticsBillRepository;
import com.syh.jn.scm.dto.downstream.logistics.DownLogisticsBillVo;
import com.syh.jn.scm.infrastructure.repository.model.logistics.LogisticsBillItemModel;
import com.syh.jn.scm.infrastructure.repository.model.logistics.LogisticsBillModel;
import com.syh.jn.scm.infrastructure.repository.utils.SQLAliasGenerateUtil;
import com.syh.jn.scm.infrastructure.wrapper.BaseResolve;
import com.syh.jn.scm.infrastructure.wrapper.ResolveToSQL;
import org.apache.ibatis.jdbc.SQL;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by soci.song on 2018/11/2.
 */
@Repository
public class DownLogisticsBillRepositoryImpl extends AbstractAggregateRepository<DownLogisticsBill, LogisticsBillModel, Long> implements DownLogisticsBillRepository {


    @Override
    public Long add(DownLogisticsBill logisticsBill) {
        Long id = super.add(logisticsBill);
        this.saveBillItems(id,logisticsBill.getItems());
        return id;
    }

    @Override
    public void update(DownLogisticsBill logisticsBill) {
        super.update(logisticsBill);
        this.removeItems(logisticsBill.getId());
        this.saveBillItems(logisticsBill.getId(), logisticsBill.getItems());
    }

    /**
     * 修改订单
     */
    @Override
    public void updateStatus(DownLogisticsBill logisticsBill) {
        super.update(logisticsBill);
    }

    @Override
    public DownLogisticsBill getById(Long id) {
        DownLogisticsBill bill = super.getById(id);
        if (bill == null) {
            return bill;
        }
        bill.setItems(this.getItemsByLogisticsBillId(id));
        return bill;
    }

    /**
     * 保存当前物流单对应的item
     *
     * @param id
     * @param items
     */
    private void saveBillItems(Long id, List<DownLogisticsBillItem> items) {
        items.stream().forEach(item -> {
            LogisticsBillItemModel itemModel = new LogisticsBillItemModel();
            ExtBeanUtils.copyProperties(item, itemModel);
            itemModel.setLogisticsBillId(id);
            this.hibernateTemplate.save(itemModel);
        });
    }

    /**
     * 删除物流单
     * @param aLong
     */
    @Override
    public void removeById(Long aLong) {
        super.removeById(aLong);
        this.removeItems(aLong);
    }

    private void removeItems(Long id) {
        StringBuffer hql = new StringBuffer();
        hql.append("from LogisticsBillItemModel model where model.logisticsBillId = ?");
        List<LogisticsBillItemModel> items = (List<LogisticsBillItemModel>) this.hibernateTemplate.find(hql.toString(),id);
        items.forEach(item -> {
            this.hibernateTemplate.delete(item);
        });
    }

    @Override
    public List<DownLogisticsBillItem> getItemsByLogisticsBillId(Long id) {
        StringBuffer hql = new StringBuffer();
        hql.append("from LogisticsBillItemModel model where model.logisticsBillId = ?");
        List<LogisticsBillItemModel> itemModels = (List<LogisticsBillItemModel>) this.hibernateTemplate.find(hql.toString(),id);
        List<DownLogisticsBillItem> items = new ArrayList<>();
        itemModels.forEach(itemModel -> {
            DownLogisticsBillItem item = new DownLogisticsBillItem();
            ExtBeanUtils.copyProperties(itemModel, item);
            items.add(item);
        });
        return items;
    }

    @Override
    protected SQL getViewSql() {
        return new SQL(){{
            SELECT(SQLAliasGenerateUtil.aliasGenerate(LogisticsBillModel.class, "downLogisticsBill", null),
                    "logisticsCompany.NAME as logisticsCompanyName,secondaryBill.ID as secondaryBillId");
            FROM("T_LOGISTICS_BILL AS downLogisticsBill");
            LEFT_OUTER_JOIN(" T_BASE_LOGISTICS logisticsCompany ON downLogisticsBill.LOGISTICS_COMPANY_ID = logisticsCompany.ID");
            LEFT_OUTER_JOIN(" ( SELECT ID, SUBJECT_BILL_ID FROM T_LOGISTICS_BILL WHERE SUBJECT_BILL_ID IS NOT NULL ) secondaryBill ON downLogisticsBill.ID = secondaryBill.SUBJECT_BILL_ID");
        }};
    }

    @Override
    protected Class getViewObject() {
        return DownLogisticsBillVo.class;
    }

    @Override
    protected BaseResolve getViewWrapperResolve(Wrapper wrapper) {
        Map<String, String> params = new HashMap<>();
        params.put("id", "downLogisticsBill.ID");
        params.put("orderType", "downLogisticsBill.ORDER_TYPE");
        params.put("code", "downLogisticsBill.CODE");
        params.put("orderCode", "downLogisticsBill.ORDER_CODE");
        params.put("customerType","downLogisticsBill.CUSTOMER_TYPE");
        params.put("customerId", "downLogisticsBill.CUSTOMER_ID");
        params.put("logisticsState", "downLogisticsBill.LOGISTICS_STATE");
        params.put("statementState", "downLogisticsBill.STATEMENT_STATE");
        params.put("statementId", "downLogisticsBill.STATEMENT_ID");
        params.put("logisticsType","downLogisticsBill.LOGISTICS_TYPE");
        params.put("logisticsCompanyId","downLogisticsBill.LOGISTICS_COMPANY_ID");
        params.put("createTimeStamp", "downLogisticsBill.CREATE_TIME_STAMP");
        params.put("businessEntityId", "downLogisticsBill.BUSINESS_ENTITY_ID");
        ResolveToSQL parse = new ResolveToSQL(wrapper, (propertyName) -> {
            return params.get(propertyName);
        });
        return parse;
    }

}
